package com.kh.pajx.sop.util.page;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.kh.pajx.sop.base.IBaseDao;
import com.kh.pajx.sop.base.IBaseService;
import com.kh.pajx.sop.domain.PageBean;
import com.opensymphony.xwork2.ActionContext;

/**
 * 用于辅助拼接生成HQL的工具类
 * @author:	azzcsimp
 * @Createdate:	2014年6月20日 下午4:18:07
 */
public class QueryHelper {

	/** From子句(必须) */
	private String fromClause;

	/** Where子句(可选) */
	private String whereClause = "";

	/** Order by子句(可选) */
	private String orderByClause = "";

	/** 参数列表 */
	private List<Object> parameters = new ArrayList<Object>();
	
	/** in 占位符与参数键值对 */
	private Map<String,List> inMap = new HashMap<String,List>();

	/**
	 * 生成From子句，默认的别名为'o'
	 * @param clazz
	 * @author: azzcsimp
	 * @Createdate: 2014年6月12日 下午3:58:01
	 */
	public QueryHelper(Class clazz) {
		this.fromClause = "From " + clazz.getSimpleName() + "o";
	}

	/**
	 * 生成From子句，使用指定的别名
	 * @param clazz
	 * @param alias 别名
	 * @author: azzcsimp
	 * @Createdate: 2014年6月12日 下午3:58:01
	 */
	public QueryHelper(Class clazz, String alias) {
		this.fromClause = "FROM " + clazz.getSimpleName() + " " + alias;
	}

	/**
	 * 拼接Where子句
	 * @param condition
	 * @param params 参数
	 * 在实际使用中可能出现多种情况，如下
	 * 	-addCondition(t.id=?", "1");-普通应用模式
	 * 	-addCondition("t.id BETWEEN ? AND ?","1","3")-需要多个参数模式
	 * 	-addCondition(t.parent IS NULL) -不需要参数模式
	 * 综上 使用变长数组来实现
	 * @return   
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月20日 下午4:25:05
	 */
	public QueryHelper addCondition(String condition, Object... params) {
		// 拼接
		if (whereClause.length() == 0) {
			whereClause = " WHERE " + condition;
		} else {
			whereClause += " AND " + condition;
		}

		// 保存参数
		if (params != null && params.length > 0) {
			for (Object obj : params) {
				parameters.add(obj);
			}
		}
		return this;
	}

	
	/**
	 * 如果第一个参数为true，则拼接Where子句
	 * 
	 * @param append
	 * @param condition
	 * @param params
	 */
	public QueryHelper addCondition(boolean append, String condition, Object... params) {
		if (append) {
			addCondition(condition, params);
		}
		return this;
	}
	
	/**
	 * 添加包含in关键字的Where条件
	 * 解析结果为 columnName in (:sign ) 参数集合为list
	 * @param columnName 列名称
	 * @param sign 占位符名称
	 * @param list 参数集合  如前端获取为数组，请使用Arrays.asList(object[])转换 
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月30日 下午3:46:59
	 */
	public QueryHelper addConditionWithIn(String columnName,String sign, List list) {
		/*// 拼接
		if (whereClause.length() == 0) {
			whereClause = " WHERE " +columnName+ " in (:"+ sign +") ";
		} else {
			whereClause += " AND " +columnName+ " in (:"+ sign +") ";
		}

		// 保存参数
		if (list != null) {
			inMap.put(sign, list);
		}
		return this;*/
		return addConditionWithIn(columnName,sign,list,true);
	}
	
	/**
	 *  添加包含in关键字的Where条件
	 *  适用于查询属性(字段/列)无表别名前缀的情况
	 * @param columnName 列名
	 * @param list 参数集合
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月30日 下午3:49:14
	 */
	public QueryHelper addConditionWithIn(String columnName, List list) {
		return addConditionWithIn(columnName,columnName,list);
	}
	
	/**
	 * 是否添加包含in关键字的Where条件
	 * @param append 是否添加
	 * @param columnName 列名
	 * @param sign 占位符名称
	 * @param list 参数集合
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月30日 下午3:51:52
	 */
	public QueryHelper addConditionWithIn(boolean append, String columnName,String sign, List list) {
		if (append) {
			addConditionWithIn(columnName, sign, list);
		}
		return this;
	}
	
	/**
	 * 是否添加包含in关键字的Where条件
	 * @param append 是否添加
	 * @param columnName 列名
	 * @param list 参数集合
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月30日 下午3:53:00
	 */
	public QueryHelper addConditionWithIn(boolean append, String columnName, List list) {
		if (append) {
			addConditionWithIn(columnName, list);
		}
		return this;
	}
	
	public QueryHelper addConditionWithIn(String columnName,String sign, List list,boolean isIn) {
		// 拼接
		if (whereClause.length() == 0) {
			whereClause = " WHERE (" +columnName+ " "+(isIn ? "IN":"NOT IN")+" (:"+ sign +")) ";
		} else {
			whereClause += " AND (" +columnName+ " "+(isIn ? "IN":"NOT IN")+" (:"+ sign +")) ";
		}

		// 保存参数
		if (list != null) {
			inMap.put(sign, list);
		}
		return this;
	}
	
	public QueryHelper addConditionWithIn(String columnName, List list,boolean isIn) {
		return addConditionWithIn(columnName,columnName,list,isIn);
	}
	
	public QueryHelper addConditionWithIn(boolean append, String columnName,String sign, List list,boolean isIn) {
		if (append) {
			addConditionWithIn(columnName, sign, list, isIn);
		}
		return this;
	}
	
	public QueryHelper addConditionWithIn(boolean append, String columnName, List list,boolean isIn) {
		if (append) {
			addConditionWithIn(columnName, list,isIn);
		}
		return this;
	}
	
	
/*	public QueryHelper addConditionWithExists(String columnName,String sign, List list,boolean isExists) {
		// 拼接
		if (whereClause.length() == 0) {
			whereClause = " WHERE (" +columnName+ " "+(isExists ? "EXISTS":"NOT EXISTS")+" (:"+ sign +")) ";
		} else {
			whereClause += " AND (" +columnName+ " "+(isExists ? "EXISTS":"NOT EXISTS")+" (:"+ sign +")) ";
		}

		// 保存参数
		if (list != null) {
			inMap.put(sign, list);
		}
		return this;
	}
	
	public QueryHelper addConditionWithExists(String columnName, List list,boolean isExists) {
		return addConditionWithExists(columnName,columnName,list,isExists);
	}
	
	public QueryHelper addConditionWithExists(boolean append, String columnName,String sign, List list,boolean isExists) {
		if (append) {
			addConditionWithExists(columnName, sign, list, isExists);
		}
		return this;
	}
	
	public QueryHelper addConditionWithExists(boolean append, String columnName, List list,boolean isExists) {
		if (append) {
			addConditionWithExists(columnName, list,isExists);
		}
		return this;
	}*/
	
	
	/**
	 * 拼接OrderBy子句
	 * 
	 * @param propertyName
	 *            属性名
	 * @param isAsc
	 *            true表示升序，false表示降序
	 */
	public QueryHelper addOrderProperty(String propertyName, boolean isAsc) {
		if (orderByClause.length() == 0) {
			orderByClause = " ORDER BY " + propertyName + (isAsc ? " ASC" : " DESC");
		} else {
			orderByClause += ", " + propertyName + (isAsc ? " ASC" : " DESC");
		}
		return this;
	}
	
	/**
	 * 拼接OrderBy语句
	 * @param propertyName 排序属性名
	 * @param sortType 排序规则  值为asc desc
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年7月1日 下午2:25:15
	 */
	public QueryHelper addOrderProperty(String propertyName,String sortType){
		if (orderByClause.length() == 0) {
			orderByClause = " ORDER BY " + propertyName + " " + sortType;
		} else {
			orderByClause += ", " + propertyName + " " + sortType;
		}
		return this;
	}
	
	/**
	 * 如果第一个参数为true 则拼接orderby语句
	 * @param append 是否拼接
	 * @param propertyName 排序属性名
	 * @param sortType 排序规则  值为asc desc
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年7月1日 下午2:26:16
	 */
	public QueryHelper addOrderProperty(boolean append, String propertyName, String sortType) {
		if (append) {
			addOrderProperty(propertyName, sortType);
		}
		return this;
	}
	
	/**
	 * 如果第一个参数为true，则拼接OrderBy子句
	 * 
	 * @param append
	 * @param propertyName
	 * @param asc
	 */
	public QueryHelper addOrderProperty(boolean append, String propertyName, boolean isAsc) {
		if (append) {
			addOrderProperty(propertyName, isAsc);
		}
		return this;
	}
	
	
	/**
	 * 获取生成的用于查询数据列表的HQL语句
	 * 
	 * @return
	 */
	public String getListQueryHql() {
		return fromClause + whereClause + orderByClause;
	}
	
	/**
	 * 获取生成的用于查询总记录数的HQL语句
	 * 
	 * @return
	 */
	public String getCountQueryHql() {
		return "SELECT COUNT(*) " + fromClause + whereClause;
	}
	
	/**
	 * 获取参数列表，与HQL过滤条件中的'?'一一对应
	 * 
	 * @return
	 */
	public List<Object> getParameters() {
		return parameters;
	}
	
	public Map<String,List> getInMap(){
		return inMap;
	}
	
	/**
	 * 查询分页信息，并放到值栈栈顶
	 * 
	 * @param service
	 * @param pageNum
	 * @param pageSize
	 */
	public void preparePageBean(IBaseDao<?> dao, int pageNum, int pageSize) {
		PageBean pageBean = dao.getPageBean(pageNum, pageSize, this);
		ActionContext.getContext().getValueStack().push(pageBean);
	}
	
	
	/**
	 * 封装分页信息，并放到值栈栈顶
	 * 封装具体内容查看PageBean
	 * @param service 业务层方法
	 * @param pageNum 当前页码
	 * @param pageSize 每页显示的数量
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月24日 下午3:07:10
	 */
	public void preparePageBean(IBaseService<?> service, int pageNum, int pageSize) {
		PageBean pageBean = service.getPageBean(pageNum, pageSize, this);
		ActionContext.getContext().getValueStack().push(pageBean);
	}
	
	/**
	 * 封装列表信息 无分页，查询全部
	 * @param service
	 * @return   
	 * @author:	azzcsimp
	 * @Createdate:	2014年9月15日 下午5:41:57
	 
	public List<Object> prepareList(IBaseService<?> service){
		return service.getListByQueryHelper(this);
	}*/
	
	/**
	 * 封装列表信息 无分页，查询全部
	 * @param dao
	 * @return   
	 * @author:	azzcsimp
	 * @Createdate:	2014年9月15日 下午5:42:07
	 
	public  List<Object> prepareList(IBaseDao<?> dao){
		return dao.getListByQueryHelper(this);
	}*/
	
	
	public static void main(String[] args) {
		/*System.out.println(new QueryHelper(Demo.class,"d")
			.addCondition("id in (?)", 1,2,3,4,5,6)
			.getListQueryHql()
				);*/
	}
	
}
